package main

import (
	"context"
	"fmt"
	"time"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// 任务的执行时间点
type TimePoint struct {
	StartTime int64 `bson:"startTime"`
	EndTime   int64 `bson:"endTime"`
}

// 一条日志
type LogRecord struct {
	JobName   string    `bson:"jobName"`   // 任务名
	Command   string    `bson:"command"`   // shell命令
	Err       string    `bson:"err"`       // 脚本错误
	Content   string    `bson:"content"`   // 脚本输出
	TimePoint TimePoint `bson:"timePoint"` // 执行时间点
}

// jobName过滤条件
type FindByJobName struct {
	JobName string `bson:"jobName"` // JobName赋值为job10
}

func main() {
	// mongodb读取回来的是bson，需要反序列为LogRecord对象
	var (
		client     *mongo.Client
		err        error
		opt        *options.ClientOptions
		database   *mongo.Database
		collection *mongo.Collection
		cond       *FindByJobName       // 条件对象
		findopt    *options.FindOptions // 翻页对象
		cursor     *mongo.Cursor        // 游标
		record     *LogRecord           // 反序列化接收值
	)

	// 1.建立连接
	opt = options.Client() // 生成一个Clientopt
	opt.ApplyURI("mongodb://127.0.0.1:27017")
	opt.SetConnectTimeout(5 * time.Second)

	if client, err = mongo.Connect(context.TODO(), opt); err != nil {
		fmt.Println(err)
		return
	}

	// 2.选择数据库my_db
	database = client.Database("cron")

	// 3.选择表my_collection
	collection = database.Collection("log")

	// 4.按照jobName字段过滤，向找出jobName=job10，找出5条
	// filter interface{}是过滤条件，定义一个结构体即可
	cond = &FindByJobName{JobName: "job10"} // {"jpbName": "job10"}

	// 定义翻页对象
	findopt = options.Find()
	findopt.SetSkip(0)  // 相当于mysql中的offset，满足条件的偏移量
	findopt.SetLimit(2) // 相当于mysql中的limit，一页的数据条数

	// 5.查询 (过滤 + 翻页参数)
	if cursor, err = collection.Find(context.TODO(), cond, findopt); err != nil {
		fmt.Println(err)
		return
	}

	// 延迟释放游标，需要释放资源
	defer cursor.Close(context.TODO())

	// 6.遍历结果集
	// Next()获取满足条件的下一条记录，多条记录需要循环Next
	// context用来控制Next的超时时间，context.TODO()表示不设置时间，无限等待
	for cursor.Next(context.TODO()) {
		// 每次调用Next，会取出一条记录并返回到cursor游标里面，需要使用Decode()方法反序列化

		// 定义一个日志对象
		record = &LogRecord{}

		// 反序列化bson到对象
		if err = cursor.Decode(record); err != nil {
			fmt.Println(err)
			return
		}

		// 把日志行打印出来
		fmt.Println(*record)
	}

}
